﻿using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using ZeroSum.Domain.Entities;
using ZeroSum.Domain.Repositories;
using ZeroSum.Domain.UnitOfWork;

namespace ZeroSum.Extend.EFCore.MySql.EntityFrameworks;

/// <summary>
///     泛型仓库
/// </summary>
/// <typeparam name="TDbContext"></typeparam>
/// <typeparam name="TEntity"></typeparam>
public class EfCoreRepository<TDbContext, TEntity> : EfCoreRepository<TDbContext>, IRepository<TEntity>
    where TDbContext : DbContext
    where TEntity : class, IEntity
{
    public EfCoreRepository(TDbContext dbContext, IUnitOfWork unitOfWork) : base(dbContext, unitOfWork)
    {
    }

    public TEntity Add([NotNull] TEntity entity)
    {
        return base.Add(entity);
    }

    public async Task<TEntity> AddAsync([NotNull] TEntity entity)
    {
        return await base.AddAsync(entity);
    }

    public void AddRange(IEnumerable<TEntity> entities)
    {
        base.AddRange(entities);
    }

    public async Task AddRangeAsync(IEnumerable<TEntity> entities)
    {
        await base.AddRangeAsync(entities);
    }

    public TEntity Update([NotNull] TEntity entity)
    {
        return base.Update(entity);
    }

    public async Task<TEntity> UpdateAsync([NotNull] TEntity entity)
    {
        return await base.UpdateAsync(entity);
    }

    public void UpdateRange(IEnumerable<TEntity> entities)
    {
        base.UpdateRange(entities);
    }

    public async Task UpdateRangeAsync(IEnumerable<TEntity> entities)
    {
        await base.UpdateRangeAsync(entities);
    }

    public IQueryable<TEntity> Query()
    {
        return base.Query<TEntity>();
    }

    public TEntity Get(IQuery<TEntity> query)
    {
        return base.Get(query);
    }

    public async Task<TEntity> GetAsync(IQuery<TEntity> query)
    {
        return await base.GetAsync(query);
    }

    public IList<TEntity> GetList(IQuery<TEntity> query)
    {
        return base.GetList(query);
    }

    public async Task<IList<TEntity>> GetListAsync(IQuery<TEntity> query)
    {
        return await base.GetListAsync(query);
    }

    public TEntity Get([NotNull] Expression<Func<TEntity, bool>> predicate)
    {
        return base.Get(predicate);
    }

    public async Task<TEntity> GetAsync([NotNull] Expression<Func<TEntity, bool>> predicate)
    {
        return await base.GetAsync(predicate);
    }

    public IList<TEntity> GetList([NotNull] Expression<Func<TEntity, bool>> predicate)
    {
        return base.GetList(predicate);
    }

    public async Task<IList<TEntity>> GetListAsync([NotNull] Expression<Func<TEntity, bool>> predicate)
    {
        return await base.GetListAsync(predicate);
    }

    public IList<TEntity> GetPage(int pageNumber, int pageSize, Expression<Func<TEntity, object>> sorting)
    {
        return base.GetPage(pageNumber, pageSize, sorting);
    }

    public async Task<IList<TEntity>> GetPageAsync(int pageNumber, int pageSize,
        Expression<Func<TEntity, object>> sorting)
    {
        return await base.GetPageAsync(pageNumber, pageSize, sorting);
    }

    public void Remove([NotNull] TEntity entity)
    {
        base.Remove(entity);
    }

    public async Task RemoveAsync([NotNull] TEntity entity)
    {
        await base.RemoveAsync(entity);
    }

    public void Remove([NotNull] Expression<Func<TEntity, bool>> predicate)
    {
        base.Remove(predicate);
    }

    public async Task RemoveAsync([NotNull] Expression<Func<TEntity, bool>> predicate)
    {
        await base.RemoveAsync(predicate);
    }

    public void RemoveRange(IEnumerable<TEntity> entities)
    {
        base.RemoveRange(entities);
    }

    public async Task RemoveRangeAsync(IEnumerable<TEntity> entities)
    {
        await base.RemoveRangeAsync(entities);
    }

    public void RemoveRange(Expression<Func<TEntity, bool>> predicate)
    {
        base.RemoveRange(predicate);
    }

    public void RemoveRange()
    {
        base.RemoveRange<TEntity>();
    }

    public async Task RemoveRangeAsync(Expression<Func<TEntity, bool>> predicate)
    {
        await base.RemoveRangeAsync(predicate);
    }

    public void Remove(IQuery<TEntity> query)
    {
        base.Remove(query);
    }

    public async Task RemoveAsync(IQuery<TEntity> query)
    {
        await base.RemoveAsync(query);
    }

    public void RemoveRange(IQuery<TEntity> query)
    {
        base.RemoveRange(query);
    }

    public async Task RemoveRangeAsync(IQuery<TEntity> query)
    {
        await base.RemoveRangeAsync(query);
    }

    public int Count()
    {
        return base.Count<TEntity>();
    }

    public async Task<int> CountAsync()
    {
        return await base.CountAsync<TEntity>();
    }

    public bool Any(Expression<Func<TEntity, bool>> predicate)
    {
        return base.Any(predicate);
    }

    public async Task<bool> AnyAsync(Expression<Func<TEntity, bool>> predicate)
    {
        return await base.AnyAsync(predicate);
    }

    public bool Existed(IQuery<TEntity> query)
    {
        return base.Existed(query);
    }

    public async Task<bool> ExistedAsync(IQuery<TEntity> query)
    {
        return await base.ExistedAsync(query);
    }

    public int Count(IQuery<TEntity> query)
    {
        return base.Count(query);
    }

    public async Task<int> CountAsync(IQuery<TEntity> query)
    {
        return await base.CountAsync(query);
    }
}

/// <summary>
///     泛型仓库（带逐渐类型约束）
/// </summary>
/// <typeparam name="TDbContext"></typeparam>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
public class EfCoreRepository<TDbContext, TEntity, TKey> :
    EfCoreRepository<TDbContext, TEntity>, IRepository<TEntity, TKey>
    where TDbContext : DbContext
    where TEntity : BaseEntity<TKey>
{
    protected EfCoreRepository(TDbContext dbContext, IUnitOfWork unitOfWork) : base(dbContext, unitOfWork)
    {
    }

    public TEntity Get(TKey id)
    {
        return Get(x => x.Id!.Equals(id));
    }

    public virtual async Task<TEntity> GetAsync(TKey id)
    {
        return await GetAsync(x => x.Id!.Equals(id));
    }

    public void Remove(TKey id)
    {
        Remove(x => x.Id!.Equals(id));
    }

    public virtual async Task RemoveAsync(TKey id)
    {
        await RemoveAsync(x => x.Id!.Equals(id));
    }

    public void RemoveRange(IEnumerable<TKey> ids)
    {
        RemoveRange(x => ids.Contains(x.Id));
    }

    public virtual async Task RemoveRangeAsync(IEnumerable<TKey> ids)
    {
        await RemoveRangeAsync(x => ids.Contains(x.Id));
    }
}